package com.antler.smt.portal.service.impl;

import com.antler.smt.constant.WeChatPayConstant;
import com.antler.smt.entity.ItemsEntity;
import com.antler.smt.portal.utils.PayCommonUtil;
import com.antler.smt.service.portal.WeChatPayService;
import com.antler.smt.utils.DateFormatUtil;
import com.antler.smt.utils.LogUtil;
import com.antler.smt.utils.XMLUtil4jdom;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import org.slf4j.Logger;
import org.springframework.boot.configurationprocessor.json.JSONObject;
import org.springframework.stereotype.Service;
import org.springframework.ui.ModelMap;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;

import static org.slf4j.helpers.Util.report;

/**
 * 微信支付接口实现
 *
 * @author zhangyi
 * @date 2018/6/4 15:17
 */
@Service
public class WeChatPayServiceImpl implements WeChatPayService {

    private static final int BLACK = 0xFF000000;
    private static final int WHITE = 0xFFFFFFFF;

    /**
     * 日志
     */
    private static Logger log = LogUtil.get();

    /**
     * 根据链接生成二维码图片
     *
     * @param request
     * @param response
     */
    @Override
    public void qrCode(ItemsEntity itemsEntity,HttpServletRequest request, HttpServletResponse response) {
        //传入的参数
        String params = "";

        //生成连接
        String urlCode = getUrlCode(itemsEntity, params);
        try {
            genGR(urlCode, response.getOutputStream());
        }catch (Exception e){
            log.error("生成二维码错误！",e);
        }

    }

    public static void genGR(String website, OutputStream output) throws WriterException, IOException {
        int width = 300;
        int height = 300;
        String format = "jpg";
        Hashtable<EncodeHintType, String> hints = new Hashtable();
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        BitMatrix bm = new MultiFormatWriter().encode(website, BarcodeFormat.QR_CODE, width, height, hints);

        BufferedImage image = toImage(bm);
        ImageIO.write(image, format, output);
    }

    private static BufferedImage toImage(BitMatrix bm) {
        int width = bm.getWidth();
        int height = bm.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for(int x = 0;x < width; x++){
            for(int y = 0; y < height; y++ ){
                image.setRGB(x, y, bm.get(x, y) ? BLACK : WHITE);
            }
        }
        return image;
    }
    /**
     * 生成支付连接用于转换成二维码,生成指定的URL weixin://wxpay/bizpayurl?pr=pIxXXXX
     *
     * @param itemsEntity
     * @param params
     * @return
     */
    public String getUrlCode(ItemsEntity itemsEntity,String params) {
        JSONObject retJson = new JSONObject();

        //产品id随机生成
        String productId = "";

        try {
            //生成8位随机数
            String currTime = PayCommonUtil.getCurrTime();
            String strTime = currTime.substring(8, currTime.length());
            String strRandom = PayCommonUtil.buildRandom(4) + "";
            String nonce_str = strTime + strRandom;

            JSONObject requestObj = new JSONObject(params);

            // 正式上线的时候价格根据订单id查询
            SortedMap<Object, Object> packageParams = new TreeMap();
            //公众号id
            packageParams.put("appid", WeChatPayConstant.APP_ID);
            //商户号
            packageParams.put("mch_id", WeChatPayConstant.MCH_ID);
            //随机字符串
            packageParams.put("nonce_str", nonce_str);
            //商品描述
            packageParams.put("body", WeChatPayConstant.BODY+itemsEntity.getItemName());
            //商品订单号
            packageParams.put("out_trade_no", itemsEntity.getOrderNo());
            //交易币种
            packageParams.put("fee_type", "CNY");
            //标价金额
            packageParams.put("total_fee", itemsEntity.getPrice());
            //客户交易的ip地址
            packageParams.put("spbill_create_ip", itemsEntity.getLoacalIp());
            //通知地址 异步接收微信支付结果通知的回调地址，通知url必须为外网可访问的url，不能携带参数
            packageParams.put("notify_url", WeChatPayConstant.NOTIFY_URL);
            //交易类型  NATIVE：扫码支付
            packageParams.put("trade_type", "NATIVE");
            //商品ID 此参数为二维码中包含的商品ID
            packageParams.put("product_id", productId);
            //获取时间模型
            Calendar nowTime = Calendar.getInstance();
            //交易起始时间
            packageParams.put("time_start", DateFormatUtil.formatDate(
                    nowTime.getTime(), "yyyyMMddHHmmss"));
            nowTime.add(Calendar.MINUTE, requestObj.getInt("expire_time"));
            //交易结束时间
            packageParams.put("time_expire", DateFormatUtil.formatDate(
                    nowTime.getTime(), "yyyyMMddHHmmss"));

            String sign = PayCommonUtil.createSign("UTF-8", packageParams,WeChatPayConstant.APP_KEY);
            //签名
            packageParams.put("sign", sign);
            //签名加密规则
            packageParams.put("sign_type", "MD5");
            String requestXML = PayCommonUtil.getRequestXml(packageParams);

            long startTime=System.currentTimeMillis();
            String resXml = PayCommonUtil.post(
                    "https://api.mch.weixin.qq.com/pay/unifiedorder",
                    requestXML);
            long endTime=System.currentTimeMillis();
            Integer execute_time = (int) ((endTime-startTime)/1000);
            Map map = XMLUtil4jdom.doXMLParse(resXml);


            JSONObject reportParams = new JSONObject();
            reportParams.put("url", "https://api.mch.weixin.qq.com/pay/unifiedorder");
            reportParams.put("execute_time", execute_time);
            reportParams.put("return_code", map.get("return_code").toString());
            reportParams.put("return_msg", map.get("return_msg").toString());
            reportParams.put("result_code", map.get("result_code").toString());

            if (map.get("err_code") != null) {
                reportParams.put("err_code", map.get("err_code").toString());
                reportParams.put("err_code_des", map.get("err_code_des").toString());
            }
            reportParams.put("out_trade_no", itemsEntity.getOrderNo());

            //输出显示
            report(reportParams.toString());

            if (map.get("return_code").toString().equals("SUCCESS") && map.get("result_code").toString().equals("SUCCESS")) {
                String urlCode = (String) map.get("code_url");
                retJson.put("code", 0);
                retJson.put("message", "下单成功.");
                retJson.put("data", urlCode);
            } else {
                retJson.put("code", 1);
                retJson.put("message", map.get("err_code_des").toString());
                retJson.put("data", "");
            }
            return retJson.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
